package com.nxcy.mongo;


import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.client.*;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;

import static com.mongodb.client.model.Indexes.descending;

public class TestMongo {

	MongoClient client = null;
	MongoDatabase g08 = null;
	MongoCollection<Document> student = null;

	@Before
	public void inti() {
		client = MongoClients.create("mongodb://g08:abc%408@mongo.zhledu.cn:27017/g08");
		g08 = client.getDatabase("g08");
		student = g08.getCollection("student");
	}

	@Test
	public void testListDatabases() {
		MongoIterable<String> list = client.listDatabaseNames();
		for (String name : list) {
			System.out.println(name);
		}
	}

	/*
	 * 创建集合
	 */
	@Test
	public void testcreateCollection() {
		g08.createCollection("student_test_01");
	}

	/***
	 * 列举出指定数据库中所有的集合名称
	 */
	@Test
	public void testListCollections() {
		MongoIterable<String> list = g08.listCollectionNames();
		for (String name : list) {
			System.out.println(name);
		}
	}

	/*
	 * 删除集合
	 */
	@Test
	public void testdropCollection() {
		MongoCollection<Document> student_test = g08.getCollection("student_test_01");
		student_test.drop();
	}

	/***
	 * 插入一个文档
	 */
	@Test
	public void testInsertOne() {
		Document document = new Document().append("name", "孙悟空").append("sno", "202019562356").append("sex", "男")
				.append("age", 1500).append("major", "佛学").append("idCard", "420602198607214513").append("state", 1);
		student.insertOne(document);
	}
	
    /**
     * 插入多条数据
     */
    @Test
    public void testInsertMany() {
        List<Document> list = new ArrayList<>();
        for (int i = 1; i <= 100; i++) {
            Document document = new Document()
            		.append("name", "孙悟空" + i)
                    .append("sno", (Long.valueOf("20201956265") + i))
                    .append("sex", "男")
                    .append("age", 1500)
                    .append("major", "佛学")
                    .append("idCard", "420602198607214513")
                    .append("state", 1);
            list.add(document);
        }
        student.insertMany(list);
    }
    
    
    /***
     * 修改单条数据
     */
    @Test
    public void testUpdateOne() {
    	Document where = new Document("name", "孙悟空");
        Document set = new Document("$set", new Document("name", "齐天大圣孙悟空"));
        UpdateResult result = student.updateOne(where, set);
        System.out.println("匹配上条数:" + result.getMatchedCount());
        System.out.println("修改成功:" + result.getModifiedCount());
    }
    
    /*
     * 更新多条文档
     */
    @Test
    public void testupdateDocument() {       
        Document set = new Document("$set", new Document("name", "齐天大圣孙悟空"));
        Document where = new Document("name",Pattern.compile("孙悟空") );
        UpdateResult result = student.updateMany(where, set);
        System.out.println("匹配上条数:" + result.getMatchedCount());
        System.out.println("修改成功:" + result.getModifiedCount());
    }
    
    
    @Test
    public void testDeleteDocument()
    {
        DeleteResult result=student.deleteOne(new Document("name", "齐天大圣孙悟空"));
        System.out.println("删除条数:" + result.getDeletedCount());       
    }
    
    @Test
    public void testDeleteManyDocument()
    {
    	Document query=new Document("name", "齐天大圣孙悟空");
        DeleteResult result=student.deleteMany(query);
        System.out.println("删除条数:" + result.getDeletedCount());       
    }	

	@Test
	public void testSimplestQuery() {
		Document query = new Document("name",Pattern.compile("孙悟空") );
		FindIterable<Document> list = student.find(query);
		for (Document d : list) {
			System.out.println(d);
		}
	}

    @Test
    public void testQueryMax() {
        Document query = new Document("name",Pattern.compile("孙悟空") );
       // FindIterable<Document> list = student.find().max(new Document("$sort",new Document("age",1)));
        Document dd=student.find(new Document("sno",new Document("$ne",null))).sort(descending("sno")).first();
        System.out.println(dd);

        /*for (Document d : list) {
            System.out.println(d);
        }*/
    }


    /***
     分页查询
      //db.student.find().skip(200).limit(10)
      //db.student.aggregate([{$skip:200},{$limit:10}])
     */
    @Test
    public void testPageQuery(){
        //为了防止数据取得多，跳过200条记录，查询10条记录
        FindIterable<Document>  list=student.find().skip(200).limit(10);
        int count=0;
        for(Document d:list){
        	System.out.println(d);
            count++;
        }
        System.out.println("一共查询到："+count+"条文档");
    }
    
    /**
     * 简单查询（带有正则表达式）查询18岁姓张的男同学
     * db.student.find({"sex":"男","age":18,"name":/^张/})
     * db.student.find({"$and":[{"sex":"男"},{"age":18},{"name":/^张/}]})
     */
    @Test
    public void testSimpleQuery(){
        //Document query=Document.parse("{\"sex\":\"男\",\"age\":18,\"name\":/^张/}");
        //BasicDBObject query=new BasicDBObject("sex", "男").append("age", 18).append("name", Pattern.compile("^张"));
        //Document query=new Document("sex", "男").append("age", 18).append("name", Pattern.compile("^张"));
        //Bson query= Filters.and(Filters.eq("sex", "男"),Filters.eq("age", 18),Filters.regex("name", Pattern.compile("^张")));

        
       BasicDBList queryList=new BasicDBList();//其中list可以使用ArrayList<Bson>代替
        queryList.add(new BasicDBObject("sex","男"));
        queryList.add(new BasicDBObject("age",18));
        queryList.add(new BasicDBObject("name",Pattern.compile("^张")));
        BasicDBObject query=new BasicDBObject("$and",queryList);

        long num=student.count(query);
        System.out.println("一共查询到："+num+"条文档");

        FindIterable<Document>  list=student.find(query);

        int count=0;
        for(Document d:list){
        	 System.out.println(d); 
            count++;
        }
        System.out.println("一共查询到："+count+"条文档");
    }
    
    
    /**
     * 管道查询
     * db.student.aggregate([{"$match":{"age":{"$gte":3,"$lte":60}}},{"$group":{"_id":"$major","avgAge":{"$avg":"$age"}}}]);
     */
    @Test
    public void testPiplineQuery(){
      List<Bson> pipList=new ArrayList<>();
      //match放在group前面相当于where，放在group后面相当于having
      Bson match=new Document("$match",new Document("age",new Document("$lte",60).append("$gte", 3)));
      Bson group=new Document("$group",new Document("_id","$major").append("avgAge", new Document("$avg","$age")));
      Bson sort=new Document("$sort",new Document("_id",1));
      Bson limit=new Document("$limit",6);
      Bson skip=new Document("$skip",1);
      pipList.add(match);
      pipList.add(group);
      pipList.add(sort);
      pipList.add(skip);
      pipList.add(limit);

      AggregateIterable<Document> list= student.aggregate(pipList);  
      int count=0;
        for(Document d:list){
        	System.out.println(d); 
            count++;
        }
        System.out.println("一共查询到："+count+"条文档");

    }
    
    /**
     * 聚合查询
     * 查询出按照专业分类年龄在16到24岁之间的所有学生的平均年龄，最大年龄，最小年龄，年龄总和，以及总人数，最后过滤到人数少于800的专业，结果按照总人数升序排序
     *db.student.aggregate([
											{
											"$match":{"age":{"$gt":17,"$lt":25}}
											},
											{"$group":
													{
														"_id":"$major",
														"avgAge":{"$avg":"$age"},
														"maxAge":{"$max":"$age"},
														"minAge":{"$min":"$age"},
														"sumAge":{"$sum":"$age"},
														"count":{"$sum":1}
														}
												},
												{
												"$match":{"count":{"$gte":800}}
												},
												{
												"$sort":{"count":1}
												}
											]);
     */
    @Test
    public void testAggragatQuery(){     
      List<Bson> pipList=new LinkedList<>();
      //match放在group前面相当于where，放在group后面相当于having
      Bson select=new Document("$match",new Document("age",new Document("$lte",24).append("$gte", 18)));
      
      Bson group=new Document("$group",
    		         new Document("_id","$major")
                     .append("avgAge", new Document("$avg","$age"))
                     .append("maxAge", new Document("$max","$age"))
                     .append("minAge", new Document("$min","$age"))
                     .append("totleAge", new Document("$sum","$age"))
                     .append("count", new Document("$sum",1)));

    Bson having=new Document("$match",new Document("count",new Document("$gte",800)));
    Bson sort=new Document("$sort",new Document("count",1));
      pipList.add(select);
      pipList.add(group);
      pipList.add(having);
      pipList.add(sort);
      AggregateIterable<Document> list= student.aggregate(pipList);  
      int count=0;
        for(Document d:list){
        	System.out.println(d); 
            count++;
        }
        System.out.println("一共查询到："+count+"条文档");

    }
    
    @Test
    public void testMapReduceQuery(){
        String map="function(){emit(this.idCard.substr(0,2), 1);}";
        String reduce="function (key, values) {	return Array.sum(values);}";

        MapReduceIterable<Document> list=student.mapReduce(map, reduce); 
        int count=0;
            for(Document d:list){
            	System.out.println(d); 
                count++;
            }
            System.out.println("一共查询到："+count+"条文档");

        }  
	
	
	
	@After
	public void close() {
		try {
			client.close();
			System.out.println("数据库连接关闭");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
